#include "xen/sdl_window.hpp"

namespace Xen {

Window* Window::Create(const WindowProps& props) {
    SDLWindow* window = new SDLWindow(props.title.c_str(), props.width, props.height);
    Log::GetCoreLogger()->trace("window created");
    return window;
}

SDLWindow::SDLWindow(const char* title, int w, int h) {
    window_ = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, w, h, SDL_WINDOW_SHOWN|SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);
    context_ = new OpenGLContext(window_);
    context_->Init();
}

SDLWindow::~SDLWindow() {
    delete context_;
    Log::GetCoreLogger()->trace("after delete gl platform");
    SDL_DestroyWindow(window_);
    Log::GetCoreLogger()->trace("after delete window");
}

Sizeu SDLWindow::GetSize() const {
    int w, h;
    SDL_GetWindowSize(window_, &w, &h);
    return {static_cast<unsigned int>(w), static_cast<unsigned int>(h)};
}

void SDLWindow::OnUpdate() const {
    pollEvent();
    context_->SwapBuffers();
    SDL_Delay(30);
}

void SDLWindow::pollEvent() const {
    SDL_Event event;
    while (SDL_PollEvent(&event)) {
        if (cb_) {
            switch (event.type) {
                case SDL_QUIT: {
                    WindowCloseEvent close_event;
                    cb_(close_event);
                    break;
                }
                case SDL_KEYDOWN: {
                    KeyPressedEvent key_pressed_event(static_cast<Keycode>(event.key.keysym.scancode), event.key.repeat);
                    cb_(key_pressed_event);
                    break;
                }
                case SDL_KEYUP: {
                    KeyReleasedEvent key_released_event(static_cast<Keycode>(event.key.keysym.scancode));
                    cb_(key_released_event);
                    break;
                }
                case SDL_TEXTINPUT: {
                    KeyTypedEvent typed_event(event.text.text);
                    cb_(typed_event);
                    break;
                }
                case SDL_MOUSEMOTION: {
                    MouseMotionEvent mouse_motion_event(event.motion.x, event.motion.y, event.motion.xrel, event.motion.yrel);
                    cb_(mouse_motion_event);
                    break;
                }
                case SDL_MOUSEBUTTONDOWN: {
                    if (event.button.button == SDL_BUTTON_LEFT) {
                        MouseButtonPressedEvent mouse_button_pressed_event(MouseButton::LEFT);
                        cb_(mouse_button_pressed_event);
                    } else if (event.button.button == SDL_BUTTON_MIDDLE) {
                        MouseButtonPressedEvent mouse_button_pressed_event(MouseButton::MIDDLE);
                        cb_(mouse_button_pressed_event);
                    } else if (event.button.button == SDL_BUTTON_RIGHT) {
                        MouseButtonPressedEvent mouse_button_pressed_event(MouseButton::RIGHT);
                        cb_(mouse_button_pressed_event);
                    }
                    break;
                }
                case SDL_MOUSEBUTTONUP: {
                    if (event.button.button == SDL_BUTTON_LEFT) {
                        MouseButtonReleasedEvent mouse_button_released_event(MouseButton::LEFT);
                        cb_(mouse_button_released_event);
                    } else if (event.button.button == SDL_BUTTON_MIDDLE) {
                        MouseButtonReleasedEvent mouse_button_released_event(MouseButton::MIDDLE);
                        cb_(mouse_button_released_event);
                    } else if (event.button.button == SDL_BUTTON_RIGHT) {
                        MouseButtonReleasedEvent mouse_button_released_event(MouseButton::RIGHT);
                        cb_(mouse_button_released_event);
                    }
                    break;
                }
                case SDL_MOUSEWHEEL: {
                    MouseScrolledEvent scroll_event(event.wheel.x, event.wheel.y);
                    cb_(scroll_event);
                    break;
                }
                case SDL_WINDOWEVENT: {
                    if (event.window.event == SDL_WINDOWEVENT_RESIZED) {
                        WindowResizeEvent resize_event(event.window.data1, event.window.data2);
                        cb_(resize_event);
                    }
                    break;
                }
            }
        }
    }
}

}
